package com.anlogic.sdk.openocd;

import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;

public class OpenocdLaunchConfiguration {
	private static final String openocdLaunchId = "ilg.gnumcueclipse.debug.gdbjtag.openocd.launchConfigurationType";
	
	private ILaunchConfigurationWorkingCopy config;
	
	public OpenocdLaunchConfiguration() {
		
	}
	
	public static OpenocdLaunchConfiguration newInstance(String projName) {
		OpenocdLaunchConfiguration Instance = new OpenocdLaunchConfiguration();
		ILaunchConfigurationWorkingCopy cfg = getLaunchConfigurationWorkingCopy(projName);
		if (cfg != null) {
			Instance.config = cfg;
		} else {
			Instance.config = Instance.createConfiguration(projName);
		}
		return Instance;
	}
	
	public static OpenocdLaunchConfiguration newConfig(String projName) {
		OpenocdLaunchConfiguration Instance = new OpenocdLaunchConfiguration();
		Instance.config = Instance.newConfiguration(projName);
		return Instance;
	}
	
	protected ILaunchManager getLaunchManager() {
		return DebugPlugin.getDefault().getLaunchManager();
	}
	
	protected ILaunchConfigurationType getOpenocdLaunchConfigType() {
		return getLaunchManager().getLaunchConfigurationType(openocdLaunchId);
	}
	
	protected ILaunchConfigurationWorkingCopy createConfiguration(String projName) {
		ILaunchConfigurationWorkingCopy launchConfig = null;
		try {			
			ILaunchConfigurationType configType = getOpenocdLaunchConfigType();
			launchConfig = configType.newInstance(null, getLaunchManager().generateLaunchConfigurationName(projName));
			launchConfig.setAttribute(ConfigurationAttributes.ATTR_PROGRAM_NAME, String.format("%s.elf", projName));
			launchConfig.setAttribute(ConfigurationAttributes.ATTR_PROJECT_NAME, projName);
			setLaunchProgram(launchConfig, projName);
			launchConfig.doSave();
		} catch (CoreException e) {
			e.printStackTrace();
		}
		
		return launchConfig;
	}
	
	public ILaunchConfigurationWorkingCopy newConfiguration(String projName) {
		ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
		ILaunchConfiguration[] launchConfigs;
		try {
			launchConfigs = launchManager.getLaunchConfigurations();
			for(ILaunchConfiguration launchConfig : launchConfigs) {
				String projectName = launchConfig.getAttribute(ConfigurationAttributes.ATTR_PROJECT_NAME, "");
				if (projectName.equals(projName)) {
					launchConfig.delete();
				}
			}
		} catch (CoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return createConfiguration(projName);
	}
	
	public void doSave() {
		try {
			config.doSave();
		} catch (CoreException e) {
			e.printStackTrace();
		}
	}
	
	public void delete() {
		try {
			config.delete();
		} catch (CoreException e) {
			e.printStackTrace();
		}
	}
	
	public void setLaunchProgram(ILaunchConfigurationWorkingCopy launchConfig, String projName) {
		 IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projName);
		 IConfiguration[] projectConfigs = ManagedBuildManager.getBuildInfo((IResource)project).getManagedProject().getConfigurations();
		 for (IConfiguration cfg : projectConfigs) {
			 if(cfg.isManagedBuildOn()) {
				 launchConfig.setAttribute(ConfigurationAttributes.ATTR_PROGRAM_NAME, String.format("Debug/%s.elf", projName));
				 break;
			 } else {
				 launchConfig.setAttribute(ConfigurationAttributes.ATTR_PROGRAM_NAME, String.format("build/%s.elf", projName));
				 break;
			 }
        }
	}
	
	public static ILaunchConfigurationWorkingCopy getLaunchConfigurationWorkingCopy(String projName) {
		ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
		ILaunchConfiguration[] launchConfigs;
		try {
			launchConfigs = launchManager.getLaunchConfigurations();
			for(ILaunchConfiguration launchConfig : launchConfigs) {
				ILaunchConfigurationWorkingCopy workingCopy = launchConfig.getWorkingCopy();
				String projectName = workingCopy.getAttribute(ConfigurationAttributes.ATTR_PROJECT_NAME, "");
				if (projectName.equals(projName)) {
					return workingCopy;
				}
			}
		} catch (CoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	public void setProgram(String program) {
		config.setAttribute(ConfigurationAttributes.ATTR_PROGRAM_NAME, program);
	}
	
	// Preprocessor
	public void setDoProgramFPGA(boolean doProgramFPGA) {
		config.setAttribute(ConfigurationAttributes.DO_PROGRAM_FPGA, doProgramFPGA);
	}
	
	public void setBitstreamFile(String bitstreamFile) {
		config.setAttribute(ConfigurationAttributes.BITSTREAM_FILE, bitstreamFile);
	}
	
	public void setRunPlatformInit(boolean runPlatformInit) {
		config.setAttribute(ConfigurationAttributes.RUN_PLAT_INIT, runPlatformInit);
	}
	
	public void setTargetArchitecture(String targetArchitecture) {
		config.setAttribute(ConfigurationAttributes.TARGET_ARCHITECTURE, targetArchitecture);
	}
	
	// OpenOCD server
	public void setDoStartGdbServer(boolean doStartGdbServer) {
		config.setAttribute(ConfigurationAttributes.DO_START_GDB_SERVER, doStartGdbServer);
	}
	
	public void setGdbServerExecutable(String gdbServerExecutable) {
		config.setAttribute(ConfigurationAttributes.GDB_SERVER_EXECUTABLE, gdbServerExecutable);
	}
	
	public void setGdbServerGdbPort(int gdbServerGdbPort) {
		config.setAttribute(ConfigurationAttributes.GDB_SERVER_GDB_PORT_NUMBER, gdbServerGdbPort);
	}
	
	public void setGdbServerTelnetPort(int gdbServerTelnetPort) {
		config.setAttribute(ConfigurationAttributes.GDB_SERVER_TELNET_PORT_NUMBER, gdbServerTelnetPort);
	}
	
	public void setGdbServerTclPort(int gdbServerTclPort) {
		config.setAttribute(ConfigurationAttributes.GDB_SERVER_TCL_PORT_NUMBER, gdbServerTclPort);
	}
	
	public void setGdbServerOtherOptions(String gdbServerOtherOptions) {
		config.setAttribute(ConfigurationAttributes.GDB_SERVER_OTHER, gdbServerOtherOptions);
	}
	
	public void setGdbServerAllocateConsole(boolean doGdbServerAllocateConsole) {
		config.setAttribute(ConfigurationAttributes.DO_GDB_SERVER_ALLOCATE_CONSOLE, doGdbServerAllocateConsole);
	}
	
	// GDB client
	public void setDoStartGdbClient(boolean doStartGdbClient) {
		config.setAttribute(ConfigurationAttributes.DO_START_GDB_CLIENT, doStartGdbClient);
	}
	
	public void setUseRemoteTarget(boolean useRemoteTarget) {
		config.setAttribute(ConfigurationAttributes.ATTR_USE_REMOTE_TARGET, useRemoteTarget);
	}
	
	public void setGdbClientExecutable(String gdbClientExecutable) {
		config.setAttribute(ConfigurationAttributes.ATTR_DEBUG_NAME, gdbClientExecutable);
	}
	
	public void setGdbClientOtherOptions(String gdbClientOtherOptions) {
		config.setAttribute(ConfigurationAttributes.GDB_CLIENT_OTHER_OPTIONS, gdbClientOtherOptions);
	}
	
	public void setGdbClientOtherCommands(String gdbClientOtherCommands) {
		config.setAttribute(ConfigurationAttributes.GDB_CLIENT_OTHER_COMMANDS, gdbClientOtherCommands);
	}
	
	public void setGdbServerIP(String gdbServerIP) {
		config.setAttribute(ConfigurationAttributes.ATTR_IP_ADDRESS, gdbServerIP);
	}
	
	public void setGdbServerPort(int gdbServerPort) {
		config.setAttribute(ConfigurationAttributes.GDB_SERVER_GDB_PORT_NUMBER, gdbServerPort);
	}
	
	public void setRemotePort(int remotePort) {
		config.setAttribute(ConfigurationAttributes.ATTR_PORT_NUMBER, remotePort);
	}
	
	public void setGdbCliPort(int cliPort) {
		config.setAttribute(ConfigurationAttributes.GDB_CLIENT_CLI_PORT_NUMBER, cliPort);
	}
	
	public void setRemoteRbbPort(int port) {
		config.setAttribute(ConfigurationAttributes.REMOTE_RBB_PORT_NUMBER, port);
	}
	
	public void setAllocateTelnetConsole(boolean doAllocateTelnetConsole) {
		config.setAttribute(ConfigurationAttributes.DO_ALLOCATE_TELNET_CONSOLE, doAllocateTelnetConsole);
	}
	
	public void setRemoteTelnetPort(int port) {
		config.setAttribute(ConfigurationAttributes.REMOTE_TELNET_PORT_NUMBER, port);
	}
	
	public void setUpdateThreadlistOnSuspend(String updateThreadlistOnSuspend) {
		config.setAttribute(ConfigurationAttributes.ATTR_DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND, updateThreadlistOnSuspend);
	}
	
	public void setDoFirstReset(boolean doFirstReset) {
		config.setAttribute(ConfigurationAttributes.FIRST_RESET_TYPE, doFirstReset);
	}
	
	public void setFirstResetType(String firstResetType) {
		config.setAttribute(ConfigurationAttributes.FIRST_RESET_TYPE, firstResetType);
	}
	
	public void setEnableSemihosting(boolean enableSemihosting) {
		config.setAttribute(ConfigurationAttributes.ENABLE_SEMIHOSTING, enableSemihosting);
	}
	
	public void setDoSecondReset(boolean doSecondReset) {
		config.setAttribute(ConfigurationAttributes.DO_SECOND_RESET, doSecondReset);
	}
	
	public void setSecondResetType(String secondResetType) {
		config.setAttribute(ConfigurationAttributes.SECOND_RESET_TYPE, secondResetType);
	}
	
	public void setLoadSymbols(boolean param) {
		config.setAttribute(ConfigurationAttributes.ATTR_LOAD_SYMBOLS, param);
	}
	
	public void setLoadExecutable(boolean param) {
		config.setAttribute(ConfigurationAttributes.ATTR_LOAD_IMAGE, param);
	}
	
	public void setUseProjBinaryForSymbols(boolean param) {
		config.setAttribute(ConfigurationAttributes.ATTR_USE_PROJ_BINARY_FOR_SYMBOLS, param);
	}
	
	public void setUseProjBinaryForImage(boolean param) {
		config.setAttribute(ConfigurationAttributes.ATTR_USE_PROJ_BINARY_FOR_IMAGE, param);
	}
	
	public void setStopAt(boolean param) {
		config.setAttribute(ConfigurationAttributes.ATTR_SET_STOP_AT, param);
	}
	
	public void setStopAt(String param) {
		config.setAttribute(ConfigurationAttributes.ATTR_STOP_AT, param);
	}
	
	public void setDoContinue(boolean param) {
		config.setAttribute(ConfigurationAttributes.DO_CONTINUE, param);
	}
}
